﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using Microsoft.Phone.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Shell;
using System.ComponentModel;

namespace G.Navigate
{
    public class NavigationContext
    {
        internal NavigationContext(PhoneApplicationPage page)
        {
            this.page = page;
        }

        public IDictionary<string, string> QueryString
        {
            get
            {
                return page.NavigationContext.QueryString;
            }
        }
        private object _param;
        /// <summary>
        /// 需要残递给新页面的参数，但是必须保证该参数可以被序列化
        /// </summary>
        public object Param
        {
            get
            {
                return _param;
            }
            set
            {
                _param = value;
            }
        }
        private PhoneApplicationPage page;
    }


    public class GBasePage : PhoneApplicationPage,INotifyPropertyChanged
    {

        int count = 0;

        /// <summary>
        /// 加载数据的时候禁用APPBar
        /// </summary>
        /// <param name="msg"></param>
        public void RegisterLoading(string msg)
        {
            if (this.count == 0)
                this.IsEnabled = false;
            RegisterLoadingNoAPPbar(msg);  
         
            if (this.ApplicationBar != null)
            {
         
                foreach (Microsoft.Phone.Shell.ApplicationBarIconButton btn in this.ApplicationBar.Buttons)
                {
                    btn.IsEnabled = false;
                }
            }
        }
        /// <summary>
        /// 加载数据的时候不禁用APPBar
        /// </summary>
        public void RegisterLoadingNoAPPbar(string msg)
        {
            Microsoft.Phone.Shell.ProgressIndicator p = Microsoft.Phone.Shell.SystemTray.GetProgressIndicator(this);
            if (p == null)
            {
                p = new ProgressIndicator();
                Microsoft.Phone.Shell.SystemTray.SetProgressIndicator(this, p);
            }
            p.IsIndeterminate = true;
            p.Text = msg;
            p.IsVisible = true;
            count++;
        }

        public void UnregisterLoading()
        {
            UnregisterLoadingNoAPPbar();
            if (count == 0)
            {
                this.IsEnabled = true;
                if (this.ApplicationBar != null)
                {
                    foreach (Microsoft.Phone.Shell.ApplicationBarIconButton btn in this.ApplicationBar.Buttons)
                    {
                        btn.IsEnabled = true;
                    }
                }
            }
        }

        public void UnregisterLoadingNoAPPbar()
        {
            Microsoft.Phone.Shell.ProgressIndicator p = Microsoft.Phone.Shell.SystemTray.GetProgressIndicator(this);
            if (p != null)
            {
                if (count > 1)
                {
                    count--;
                }
                else
                {
                    p.IsIndeterminate = false;
                    p.IsVisible = false;
                    count = 0;
                }
            }
        }

        /// <summary>
        /// 当程序处于后台时，导航的连接
        /// </summary>
        public const string APPExternal = @"app://external/";

        #region 静态数据
        private static object nextPageParam;
        private const string NavigationContext_ParamKeyName = "NavigationContext_Param";
        protected static NavigateBackFromEventArgs NavigateBackFromEventArgs;
        #endregion

        public new NavigationContext NavigationContext { get; private set; }
        public GBasePage()
        {
            this.NavigationContext = new NavigationContext(this);
            this.CanUseState = true;
        }

        internal bool Navigate(string uri, object param)
        {
            nextPageParam = param;
            return this.NavigationService.Navigate(new Uri(uri, UriKind.Relative));
        }

        /// <summary>
        /// 显示状态信息并设置状态栏背景
        /// </summary>
        /// <param name="msg"></param>
        public void ShowState(string msg, Brush stateBackgroundBrush)
        {
            PhoneApplicationPageHelp.ShowState(msg, TimeSpan.FromSeconds(4), stateBackgroundBrush, null);
        }
        /// <summary>
        /// 显示状态信息
        /// </summary>
        /// <param name="msg"></param>
        public void ShowState(string msg, Action callback = null)
        {
            PhoneApplicationPageHelp.ShowState(msg, callback);
        }
        /// <summary>
        /// 将参数从State中移除，主要是因为能够被存在State中的参数必须确保能够被序列化，否则使用后第一时间删除，不然会在墓碑以后出现crash
        /// 如果能够确保使用后能够马上删除的，那么在导航的时候可以传递任何类型的参数
        /// </summary>
        protected void RemoveNagigateParam()
        {
            if (this.NavigationContext.Param != null && this.State.ContainsKey(NavigationContext_ParamKeyName))
            {
                this.State.Remove(NavigationContext_ParamKeyName);
            }
        }
        private Uri selfUrl;

        internal G.MVVM.BaseViewModel ViewModel { get; set; }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            selfUrl = e.Uri;
            if (e.NavigationMode == System.Windows.Navigation.NavigationMode.New)
            {
                if (nextPageParam != null)
                {
                    this.NavigationContext.Param = nextPageParam;
                    nextPageParam = null;
                    this.State[NavigationContext_ParamKeyName] = this.NavigationContext.Param;
                }
            }
            else if (e.NavigationMode == System.Windows.Navigation.NavigationMode.Back)
            {
                if (this.NavigationContext.Param == null)
                {
                    if (this.State.ContainsKey(NavigationContext_ParamKeyName))
                    {
                        this.NavigationContext.Param = this.State[NavigationContext_ParamKeyName];
                    }
                }
            }
            CanUseState = true;
            base.OnNavigatedTo(e);
            //当从前一页返回到当前页的时候，将从前一页返回的数据添加到当前页
            if (e.NavigationMode == NavigationMode.Back && NavigateBackFromEventArgs != null && NavigateBackFromEventArgs.HasHandle)
            {
                OnNavigatingBackFrom(NavigateBackFromEventArgs);
                NavigateBackFromEventArgs = null;
            }

            //if (ViewModel != null)
            //    ViewModel.OnNavigatedTo_Internal(e);
        }
        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {

            base.OnNavigatedFrom(e);
            //当从当前页返回到上一页的时候清空State中的数据
            if (e.NavigationMode == NavigationMode.Back)
            {
                //this.State.Clear();
                GC.Collect();//TODO:每次返回的时候调用一次内存清理，目前不知道这样做会不会影响性能，待测试
            }
            CanUseState = true;
            //if (ViewModel != null)
            //    ViewModel.OnNavigatedFrom_Internal(e);
        }

        //如果按了开始键，那个NavigatingCancelEventArgs的url=app://external/
        protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
        {
            base.OnNavigatingFrom(e);
            //当从当前页返回到前一页的时候，传递当前页的需要传递给前一页的参数，和OnNavigatedTo配合实现返回的时候回调的目的
            if (e.NavigationMode == NavigationMode.Back)
            {
                NavigateBackFromEventArgs = new G.Navigate.NavigateBackFromEventArgs();
                NavigateBackFromEventArgs.From = this.GetType();
                OnNavigatingFromBack(NavigateBackFromEventArgs);
            }
            if (this.NavigatingFrom != null)
            {
                this.NavigatingFrom(this, e);
            }
            CanUseState = false;
            //if (ViewModel != null)
            //    ViewModel.OnNavigatingFrom_Internal(e);
        }

        /// <summary>
        /// 从当前页返回到前一页的时候发生
        /// </summary>
        /// <param name="e">需要将数据返回给前一页处理，
        /// 如果有数据需要前一页处理的，
        /// 那么必须要将NavigateBackFromEventArgs的HasHandle设为True</param>
        protected virtual void OnNavigatingFromBack(NavigateBackFromEventArgs e)
        {
            //if (ViewModel != null)
            //    ViewModel.OnNavigatingFromBack_Internal(e);
        }

        /// <summary>
        /// 从前一页返回到当前页的时候发生
        /// </summary>
        /// <param name="e">需要交给本页处理的数据</param>
        protected virtual void OnNavigatingBackFrom(NavigateBackFromEventArgs e)
        {
            //if (ViewModel != null)
            //    ViewModel.OnNavigatingBackFrom_Internal(e);
        }

        /// <summary>
        /// 在页面即将不再是框架中的活动页面时调用
        /// </summary>
        public event NavigatingCancelHandler NavigatingFrom;

        private bool canUseState;
        /// <summary>
        /// 是否可以使用State
        /// </summary>
        public bool CanUseState
        {
            get
            {
                if (PhoneApplicationPageHelp.GetBasePage() != this)
                    return false;
                return canUseState;
            }
            private set
            {
                canUseState = value;
            }
        }

        public void GoBack()
        {
            if (!this.NavigationService.CanGoBack)
                return;
            foreach (var item in this.NavigationService.BackStack)
            {
                if (item.Source == this.NavigationService.Source || this.NavigationService.CurrentSource == this.selfUrl)
                {
                    this.NavigationService.GoBack();
                    break;
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged(string name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }
    public delegate void NavigatingCancelHandler(object sender, NavigatingCancelEventArgs e);
    /// <summary>
    /// 从前一页返回的时候需要回调的参数
    /// </summary>
    public class NavigateBackFromEventArgs : EventArgs
    {
        internal NavigateBackFromEventArgs()
        {

        }
        /// <summary>
        /// 指示是否需要处理
        /// </summary>
        public bool HasHandle { get; set; }
        /// <summary>
        /// 需要处理的数据
        /// </summary>
        public object Param { get; set; }


        public Type From { get; internal set; }
    }

}
